/**
 * v-showtip
 * 判断文字是否超出，超出则展示文字 toolTip 提示
 * 接收参数：Boolean
 */
import { createVNode, render } from 'vue';
import type { Directive, DirectiveBinding } from 'vue';
import { ElTooltip } from 'element-plus';

/**
 * 递归查找父节点是否存在该类名
 */
const isParent = (obj: HTMLElement, className: string) => {
    while (obj !== undefined && obj != null && obj.tagName.toUpperCase() !== 'BODY') {
        if (obj.className === className) {
            return true;
        }
        obj = obj.parentNode as HTMLElement;
    }
    return false;
};

/**
 * 判断内容是否超出，如未超出则将自带 el-tooltip 组件提示移除
 */
const compareWidth = (el: HTMLElement, value?: string) => {
    // 如果没有超出宽度，即子<父 则移除tooltip
    if (
        el.querySelector('.ellipse-text') &&
        (el.querySelector('.ellipse-text') as HTMLDivElement)?.textContent !== '--' &&
        (el.querySelector('.ellipse-text') as HTMLDivElement)?.offsetWidth > 0
    ) {
        if (value) el.querySelector('.ellipse-text')!.innerHTML = value; // 将渲染文本内容以 v-showtip="value" 形式传入，确保数据响应式
        if ((el.querySelector('.ellipse-text') as HTMLDivElement)?.offsetWidth <= el.offsetWidth) {
            if (isParent(el, 'hidden-columns')) return;
            const copySpan = el.querySelector('.ellipse-text'); // 获取到目标节点的子节点，即纯粹的span标签文案
            const toggleTip = el.querySelector('.el-tooltip__trigger');

            if (toggleTip) {
                const childVnode = createVNode('span', { class: 'ellipse-text' }, [
                    copySpan?.textContent
                ]);

                el.removeChild(toggleTip); // 移除带有el-tooltip组件的节点
                render(childVnode, el); // 将纯粹的span标签文案整体追加到目标节点的父节点
            }
        } else {
            const toggleTip = el.querySelector('.el-tooltip__trigger');

            if (toggleTip) return;
            const copySpan = el.querySelector('.ellipse-text'); // 获取到目标节点的子节点，即纯粹的span标签文案

            const childVnode = createVNode(
                ElTooltip,
                {
                    placement: 'top',
                    content: copySpan?.textContent,
                    showArrow: false,
                    rawContent: true
                },
                {
                    default: () => createVNode('p', { class: 'ellipsis' })
                }
            );

            el.removeChild(copySpan!);
            render(childVnode, el); // 将虚拟DOM chilVnode 渲染为真实 DOM
            const oEllipsis = el.querySelector('.ellipsis');
            copySpan?.classList.add('ellipse-text'); // 给当前节点设置类名 ellipse-text
            oEllipsis?.appendChild(copySpan!); // 将传入的内容添加至所创建的类名为 ellipsis 元素中
        }
    }
};

export const showtip: Directive = {
    mounted(el: HTMLElement) {
        compareWidth(el); // 可以获取到ajax数据的DOM元素，即真实的宽度
    },
    // 所在组件的 VNode 更新时调用，但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变，也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
    updated(el: HTMLElement, binding: DirectiveBinding) {
        compareWidth(el, binding.value); // 可以获取到ajax数据的DOM元素，即真实的宽度
    }
};
